学会Zynq(23)XADC报警功能与中断使用示例 您所在的位置:网站首页 vivado xadc fpga温度 学会Zynq(23)XADC报警功能与中断使用示例

学会Zynq(23)XADC报警功能与中断使用示例

2024-01-17 17:35| 来源: 网络整理| 查看: 265

上篇中我们简单了解了XADC和其基本使用方法,包括对片内温度和各种电源电压的测量。本文我们将学习XADC的报警功能和中断的使用方法。程序中我们设置温度和VCCPAUX的上、下报警阈值。当超出这个范围时,便进入中断进行报警提示。

SDK程序设计

由于要使用中断系统,我们翻出两个“老伙计”,第14篇中的sys_intr.h和sys_intr.c。将GIC初始化和串口中断初始化分开,这样当设计中有多个中断源时,编写代码会更方便。

user_xadc.h文件的代码如下:

#ifndef SRC_USER_XADC_H_ #define SRC_USER_XADC_H_ #include #include "sleep.h" #include "xil_printf.h" #include "xadcps.h" //XADC设备的支持驱动程序 #include "xscugic.h" #define XADCINTR_ID XPAR_XADCPS_INT_ID //中断ID int XADC_Init(XAdcPs* XADCMonInst); int XADC_Inter(XScuGic *Intc, XAdcPs *XAdcPtr, u16 IntrId); void XADC_Alarm_Init(XAdcPs *XAdcInstPtr); void XAdcInterruptHandler(void *CallBackRef); #endif /* SRC_USER_XADC_H_ */

user_xadc.c文件的代码如下,设计XADC的中断初始化函数、中断处理函数和报警设置函数:

#include "user_xadc.h" //--------------------------------------------------------- // XADC初始化函数 //--------------------------------------------------------- int XADC_Init(XAdcPs* XADCMonInst) { int Status; /* 初始化XADC */ XAdcPs_Config *ConfigPtr; ConfigPtr = XAdcPs_LookupConfig(XPAR_XADC_WIZ_0_DEVICE_ID); if (ConfigPtr == NULL) { xil_printf("Can't find XADC device.\r\n"); return XST_FAILURE; } Status = XAdcPs_CfgInitialize(XADCMonInst,ConfigPtr,ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { xil_printf("XADC Init FAILED!\r\n"); return XST_FAILURE; } //XADC自检 Status = XAdcPs_SelfTest(XADCMonInst); if (Status != XST_SUCCESS) { xil_printf("XADC selftest FAILED!\r\n"); return XST_FAILURE; } XAdcPs_SetSequencerMode(XADCMonInst,XADCPS_SEQ_MODE_SAFE); //默认模式,报警值不启动 XAdcPs_SetAlarmEnables(XADCMonInst, 0x0); //禁用所有报警 XAdcPs_SetSeqInputMode(XADCMonInst, XADCPS_SEQ_MODE_SAFE); //设置模拟输入模式 //设置片内温度的报警阈值 45 XAdcPs_SetAlarmThreshold(XADCMonInst, XADCPS_ATR_TEMP_UPPER,XAdcPs_TemperatureToRaw(45)); XAdcPs_SetAlarmThreshold(XADCMonInst, XADCPS_ATR_TEMP_LOWER,XAdcPs_TemperatureToRaw(20)); //设置VCCPAUX的报警阈值 1.79 XAdcPs_SetAlarmThreshold(XADCMonInst, XADCPS_ATR_VCCPAUX_UPPER,XAdcPs_VoltageToRaw(1.79)); XAdcPs_SetAlarmThreshold(XADCMonInst, XADCPS_ATR_VCCPAUX_LOWER,XAdcPs_VoltageToRaw(1.55)); xil_printf("XADC Init SUCCESS!\r\n"); return XST_SUCCESS; } //--------------------------------------------------------- // XADC中断初始化函数 //--------------------------------------------------------- int XADC_Inter(XScuGic *Intc, XAdcPs *XAdcPtr, u16 IntrId) { int Status; Status = XScuGic_Connect(Intc, IntrId, (Xil_InterruptHandler)XAdcInterruptHandler, (void *)XAdcPtr); if (Status != XST_SUCCESS) { return Status; } XScuGic_Enable(Intc, IntrId); return XST_SUCCESS; } //--------------------------------------------------------- // XADC报警功能设置 //--------------------------------------------------------- void XADC_Alarm_Init(XAdcPs *XAdcInstPtr) { u32 IntrStatus; //清除中断状态寄存器中的所有位。 IntrStatus = XAdcPs_IntrGetStatus(XAdcInstPtr); XAdcPs_IntrClear(XAdcInstPtr, IntrStatus); //使能片内温度的Alarm 0中断和VCCPAUX的Alarm 5中断 XAdcPs_IntrEnable(XAdcInstPtr, (XADCPS_INTX_ALM5_MASK | XADCPS_INTX_ALM0_MASK)); //使能对应的报警功能 XAdcPs_SetAlarmEnables(XAdcInstPtr, (XADCPS_CFR1_ALM_VCCPAUX_MASK | XADCPS_CFR1_ALM_TEMP_MASK)); XAdcPs_SetSequencerMode(XAdcInstPtr, XADCPS_SEQ_MODE_INDEPENDENT); } //--------------------------------------------------------- // XADC中断处理函数 //--------------------------------------------------------- void XAdcInterruptHandler(void *CallBackRef) { u32 IntrStatusValue; XAdcPs *XAdcPtr = (XAdcPs *)CallBackRef; u32 TempRawData, VccPAuxRawData; float TempData, VccPAuxData; // 获取中断状态标志 IntrStatusValue = XAdcPs_IntrGetStatus(XAdcPtr); // Alarm 0中断 if (IntrStatusValue & XADCPS_INTX_ALM0_MASK) { xil_printf("Temp Warning!\r\n"); TempRawData = XAdcPs_GetAdcData(XAdcPtr, XADCPS_CH_TEMP); TempData = XAdcPs_RawToTemperature(TempRawData); printf("Raw Temp %lu Real Temp %f \r\n", TempRawData, TempData); XAdcPs_IntrDisable(XAdcPtr,XADCPS_INTX_ALM0_MASK); //禁用中断 } // Alarm 5中断 if (IntrStatusValue & XADCPS_INTX_ALM5_MASK) { xil_printf("VccPAUX Warning!\r\n"); VccPAuxRawData = XAdcPs_GetAdcData(XAdcPtr, XADCPS_CH_VCCPAUX); VccPAuxData = XAdcPs_RawToVoltage(VccPAuxRawData); printf("Raw VccPAux %lu Real VccPAux %f \r\n", VccPAuxRawData, VccPAuxData); XAdcPs_IntrDisable(XAdcPtr,XADCPS_INTX_ALM5_MASK); //禁用中断 } // 清除中断状态标志 XAdcPs_IntrClear(XAdcPtr, IntrStatusValue); }

main.c文件的代码如下

//--------------------------------------------------------------- // Writen by CUIT 刘奇 2019.3.28 // 此程序为XADC报警功能和中断示例 //--------------------------------------------------------------- #include "user_xadc.h" #include "sys_intr.h" static XScuGic Intc; //GIC static XAdcPs XADCInst; //XADC void System_Init(void) { XADC_Init(&XADCInst); Init_Intr_System(&Intc); Setup_Intr_Exception(&Intc); XADC_Inter(&Intc, &XADCInst, XADCINTR_ID); XADC_Alarm_Init(&XADCInst); } int main() { System_Init(); while(1); }

测试结果如下,VCCPAUX报警很快触发。耐心等待一会,当Zynq片内温度超过45℃后,温度报警也触发。

“”

相关API函数

1.报警阈值设置

在初始化XADC时,使用XAdcPs_SetAlarmThreshold函数设置报警阈值。

void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr,u8 AlarmThrReg,u16 Value)

第二个参数是要设置的报警阈值寄存器;第三个参数时要写入的16位阈值。各种报警阈值寄存器的宏定义在xadcps.h文件中。XADC的8个报警中断共有16个报警寄存器,各有一个上阈值和下阈值。

“”

我这里只设置了温度和VCCPAUX的上、下阈值。设置阈值时借助XAdcPs_VoltageToRaw和XAdcPs_TemperatureToRaw两个“宏定义函数”将普通意义上的电压和温度值转换为寄存器中存储的值。

轻负载情况下,博主测试使用的Zynq7010在刚上电时在40℃以下,工作一段时间后会到达50~60℃之间。二VCCPAUX正常会在1.79V处浮动。我们据此设置阈值,来观察效果。

2.XADC中断初始化

初始化部分使用XScuGic_Connect和XScuGic_Enable函数设置UART中断,和前面的PL中断和定时器中断类似,不再详述。XADC中断也是一种SPI,查看第7篇中的表格。

“”

其中断号为39,在头文件中宏定义。

3.报警功能设置

这部分包括两步:使能对应的中断(XAdcPs_IntrEnable函数)和设置对应的报警功能(XAdcPs_SetAlarmEnables函数)。XADC共支持8种不同的中断Alarm0~6和过温中断(过温用XAdcPs_SetOverTemp函数设置,而不是XAdcPs_SetAlarmThreshold函数)。

下表给出了各种中断宏定义(XAdcPs_IntrEnable使用的参数)和报警宏定义(XAdcPs_SetAlarmEnables使用的参数)之间的对应关系。

中断宏定义 报警宏定义 中断 XADCPS_CFR1_ALM_TEMP_MASK XADCPS_INTX_ALM0_MASK Alarm0-温度 XADCPS_CFR1_ALM_VCCINT_MASK XADCPS_INTX_ALM1_MASK Alarm1-VCCINT XADCPS_CFR1_ALM_VCCAUX_MASK XADCPS_INTX_ALM2_MASK Alarm2-VCCAUX XADCPS_CFR1_ALM_VBRAM_MASK XADCPS_INTX_ALM3_MASK Alarm3-VBRAM XADCPS_CFR1_ALM_VCCPINT_MASK XADCPS_INTX_ALM4_MASK Alarm4-VCCPINT XADCPS_CFR1_ALM_VCCPAUX_MASK XADCPS_INTX_ALM5_MASK Alarm5-VCCPAUX XADCPS_CFR1_ALM_VCCPDRO_MASK XADCPS_INTX_ALM6_MASK Alarm6-VCCPDRO XADCPS_CFR1_OT_MASK XADCPS_INTX_OT_MASK 过温

我们这里只使用自定义温度和VCCPAUX,因此只设置Alarm0和Alarm5。

4.中断处理函数

中断处理函数的大致流程如下:

获取中断状态标志,检查触发的是哪种中断; 根据不同的中断类型,执行不同的操作,Alarm0中断则温度报警,Alarm5则VCCPAUX报警; 清除中断标志状态; 为防止超出设定的阈值后就无限进入中断,检测到一次报警便使用XAdcPs_IntrDisable函数禁用掉该中断。

但我发现当禁用了VCCPAUX中断后,虽然不会无限进入了,但是触发了温度中断后,还会再次打印出VCCPAUX的值。这说明应该是VCCPAUX超出阈值后,Alarm5仍会置位对应的中断标志位,只不过不会进入中断状态了。博主一般不会太仔细研究底层的寄存器功能结构,如果你知道背后的工作机制,一定要留言告诉我。

总结

本文介绍了XADC的报警功能和中断使用示例。本文以两种报警中断为例,使用其它XADC中断时方法类似,很容易修改。

---------------------

文章来源:FPGADesigner的博客 *本文由作者授权转发,如需转载请联系作者本人


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有